package com.fzn.spring5.service;

import com.fzn.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @program: spring5_txdemo1
 * 基于注解的方式进行事务的管理
 *
 * 描述：  Transactional 事务注解 可以添加到类上 也可以添加到奥方法上
 *          如果是添加到类上 那么所有的方法就会添加事务
 *
 *          基于注解生成声明式事务管理
 *          1.@Transactional
 *                  propagation: 事务的传播行为
 *                      多事务方法直接进行调用 这个过程中事务 是如何进行管理的
 *                      spring有7中传播行为
 *                              REQUIRED
 *                                  如果本身方法有事务 调用其他方法之后 其他方法使用当前方法里面的事务
 *                                  如果当前方法本身没有事务调用其他方法之后 创建新事务
 *                              REQUIRED_NEW
 *                                  使用当前方法去调用其他方法 无论当前方法是否有事务都会创建新的事务
 *                              SUPPORTS
 *                                  如果有事务在运行 当前的方法就在这个事务内运行 否则它可以不运行在事务中
 *                              NOT_SUPPORTS
 *                                  当前方法不应该运行在事务中 如果有运行的事务 将它挂起
 *                              MANDATORY
 *                                  当前方法必须运行在事务内部 如果没有正在运行的事务 就抛出异常
 *                               NEVER
 *                                  当前的方法不应该运行在事务中 如果有运行的事务就抛出异常
 *                               NESTED
 *                                  如果有事务在运行 当前的方法就应该在这个事务的嵌套事务内运行
 *                                  否则 就启动一个新的事务 并在它自己的是事务内运行。
 *
 *                  isolation: 事务的隔离级别
 *                     事务有特性成为隔离性 多事务操作之前不会产生影响 不考虑隔离性产生很多问题
 *                     有三个读问题：
 *                          脏读： 一个未提交事务读取到另一个未提交的数据
 *                          不可重复读：一个未提交的事务读取到另外一个提交事务修改数据
 *                          幻读：一个未提交事务读取到另外一提交事务添加数据
 *                      解决：
 *                          通过设置事务隔离级别 解决读问题
 *                                                  脏读      不可重复读      幻读
 *                     READ UNCOMMITTED（读未提交）    有           无          无
 *                     READ COMMITTED(读已提交)        无            有          有
 *                     REPEATABLE READ(可重复读)        无           无           有
 *                     SERIALIZABLE(串行化)            无           无           无
 *
 *                  timeout: 超时时间
 *                        事务需要在一定时间内进行提交 如果不提交进行回滚
 *                        默认值是-1 设置时间以秒单位进行计算
 *
 *                  readOnly: 是否只读
 *                      读：查询操作 写:添加修改删除操作
 *                      readOnly默认值是false 表示可以查询 可以添加修改修改删除操作
 *                          设置为true 设置true之后 只能查询
 *
 *                  rollbackFor： 回滚
 *                       设置出现哪些异常进行事务回滚
 *
 *                   noRollbackFor  不回滚
 *                      设置出现哪些异常不进行事务回滚
 *
 *
 * @author: fzn
 * @create: 2022-02-27 17:34
 **/
@Service
// @Transactional(timeout = -1,propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public class UserService {

    @Autowired
    private UserDao userDao;


    /**
     * 转账的操作
     */
    public void accountMoney() {
        // try {
        //     // 第一步 开启事务
        //     // 第二步 进行业务操作
        //     // lucy 少100
        //     userDao.reduceMoney();
        //     // 默认异常
        //     int i = 1/0;
        //     // mary 多100
        //     userDao.addMoney();
        //     // 第三步 没有发生异常 提交事务
        //
        // } catch (Exception e) {
        //     // 第四步 出现异常 事务回滚
        // }
        userDao.reduceMoney();
        int i = 1/0;
        userDao.addMoney();
    }
}